package com.zjcode.cdcer.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.chinatechstar.component.commons.entity.MPage;
import com.chinatechstar.component.commons.result.PaginationBuilder;
import com.chinatechstar.component.commons.service.AliyunOssService;
import com.chinatechstar.component.commons.service.BaseService;
import com.chinatechstar.component.commons.supports.PageData;
import com.chinatechstar.component.commons.utils.ExcelUtils;
import com.chinatechstar.component.commons.utils.StringUtils;
import com.chinatechstar.component.commons.utils.UuidUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zjcode.cdcer.enums.CommonEnum;
import com.zjcode.cdcer.mapper.CerTreatmentOfficalInfoMapper;
import com.zjcode.cdcer.mapper.TkmSysOrgMapper;
import com.zjcode.cdcer.mapper.TkmSysUserMapper;
import com.zjcode.cdcer.model.*;
import com.zjcode.cdcer.model.basic.JsonObj;
import com.zjcode.cdcer.model.excel.SysteminitImportInfo;
import com.zjcode.cdcer.pojo.CerSysteminitImportInfo;
import com.zjcode.cdcer.service.*;
import com.zjcode.cdcer.utils.Utils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 */
@Service
@Transactional
public class CerTreatmentOfficalInfoServiceImpl implements CerTreatmentOfficalInfoService , BaseService {

    @Autowired
    private CerTreatmentOfficalInfoMapper cerTreatmentOfficalInfoMapper;

    @Autowired
    private CerTreatmentInfoService cerTreatmentInfoService;

    @Autowired
    private TkmSysOrgMapper orgMapper;

    @Autowired
    private TkmSysUserMapper userMapper;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private CerSysteminitImportInfoService cerSysteminitImportInfoService;

    @Value("${studio.cer-personinfo-file-in-disk}")
    private String cerPersonFileInDisk;

    @Autowired
    private AliyunOssService aliyunOssService;


    /*存入正式库*/
    @Override
    public JsonObj insertOfficeInfo(PageData pageData) {
        Object data = pageData.get("data");
        if (data==null) {
            return JsonObj.error("请先勾选数据");
        }
        List<String> ids = Arrays.asList(String.valueOf(data).split("\\|"));
        // 查ids集合数据
        List<CerTreatmentInfo> cerTreatmentInfos=cerTreatmentInfoService.getTreatmentInfoByIds(ids);
        // 合格列表
        List<CerTreatmentInfo> list = cerTreatmentInfos.stream().filter(item -> item.getIsHaveError()==0).collect(Collectors.toList());
//        if (cerTreatmentInfos.size()!=list.size()) {
//            return JsonObj.error("勾选的数据，还未完善！");
//        }
        if (CollectionUtils.isEmpty(list)) {
            return JsonObj.error("勾选数据中，没有合格数据");
        }
        // 修改治疗列表的状态
        ids = list.stream().map(CerTreatmentInfo::getId).collect(Collectors.toList());
        cerTreatmentInfoService.setIsPublishByInfoIds(ids);
        list.forEach(item->{item.setId(get32UUID());});
        Integer count=cerTreatmentOfficalInfoMapper.copyTreatmentInfo(list);
        return JsonObj.success("成功存入治疗正式库"+count+"条数据");
    }

    /*查单个治疗正式库*/
    @Override
    public Map<String, Object> findById(String id) {
        Map<String, Object> data = new HashMap<>();
        CerTreatmentOfficalInfo info=cerTreatmentOfficalInfoMapper.findById(id);
        data.put(CommonEnum.RESP.getValue(), info);
        return data;
    }

    /*查询治疗正式库列表*/
    @Override
    public Map<String, Object> listAllData(PageData pageData) {
        // 获取当前用户信息
        Long userId = Long.valueOf(pageData.get("user").toString());
        TkmSysUser userInfo = userMapper.selectByPrimaryKey(userId);
        TkmSysOrg orgInfo = orgMapper.selectByPrimaryKey(userInfo.getOrgId());
        pageData.put("ancestors", orgInfo.getAncestors().replace(",", "|"));
        // 解析分页参数
        MPage mPage = getPageInfo(pageData);
        Page<Object> page = PageHelper.startPage(mPage.getCurrentPage(), mPage.getPageSize());
        List<LinkedHashMap<String, Object>> list = cerTreatmentOfficalInfoMapper.findAllList(pageData);
        return PaginationBuilder.buildResult(list,
                page.getTotal(),
                mPage.getCurrentPage(),
                mPage.getPageSize());
    }

    /*退回*/
    @Override
    public Integer returnById(String id) {
        CerTreatmentOfficalInfo info=cerTreatmentOfficalInfoMapper.findById(id);
        // 1、逻辑删除治疗正式库
        cerTreatmentOfficalInfoMapper.delOfficalById(id);
        // 2、恢复治疗列表（初始表）的状态
        /// 得到数据上报id
        String systeminitId = info.getSysteminitId();
        // `is_publish` 改成0（未发布）
        PageData pageData =new PageData();
        pageData.put("is_publish",0);
        pageData.put("del_flag",1);
        pageData.put("systeminit_id",systeminitId);
        // isHaveError：0无错，1有错，5退回
        pageData.put("isHaveError", 5);
        cerTreatmentInfoService.updateTreatmentInfo(pageData);
        return 1;
    }

    @Override
    public List<LinkedHashMap<String, Object>> queryAllExportData(PageData pageData) {
        String userId = (String) pageData.get("user");
        Object idsData = pageData.get("ids");
        String extFlag = sysUserService.findUserExtFlag(userId);
        pageData.put("extFlag", extFlag);
        List<String> ids = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(idsData)) {
            ids = Arrays.asList(String.valueOf(idsData).split("\\|"));
        }
        List<LinkedHashMap<String, Object>> list = cerTreatmentOfficalInfoMapper.queryAllExportData(idsData, ids,pageData);

        // 查询数据自定并分组
        List<SysDict> allCerDicts = sysDictService.findAllCerDicts();
        Map<String, List<SysDict>> keyListMap = allCerDicts
                .stream()
                .collect(Collectors.groupingBy(SysDict::getDictType));
        keyListMap.entrySet().parallelStream().forEach(entry -> {
            // key
            String key = entry.getKey();
            List<SysDict> dicts = entry.getValue();
            list.parallelStream().forEach(item->{
                Object o = item.get(key);
                if (o!=null) {
                    Optional<SysDict> first = dicts.stream()
                            .filter(sysDict -> sysDict.getDictValue().equals(o.toString())).findFirst();
                    first.ifPresent(sysDict -> {
                        item.put(key, sysDict.getDictName());
                    });
                }
            });
        });
        return list;
    }

    /**
     * 治疗正式库导入国家数据结构业务分析：
     * 1、先判断screening_id有没有  --  判断初始临时表存不存在该值
     *  => 1.1、没有，报错、“初始上报和初始正式库都没有该人员信息”
     *     1.2、 有，先判断正式库存不存在该值，（1）存在，报错，提示“正式库已存在”
     *     （2）不存在，查治疗列表是否存在，① 不存在，补充治疗列表数据和治疗正式库相应数据 ②存在，增加治疗正式库数据
     * @param file
     * @param response
     * @param userId
     * @return
     */
    @Override
    public JsonObj importGJData(MultipartFile file, HttpServletResponse response, String userId) {
        ImportParams params = new ImportParams();
        params.setTitleRows(0);
        File tmpfile =cerSysteminitImportInfoService.commonImportConfig(file,userId);
        // 解析excel
        List<SysteminitImportInfo> list = ExcelImportUtil.importExcel(tmpfile, SysteminitImportInfo.class, params);
        // 数据过滤,国家来源的数据默认都是正确的，仅过滤名称为null的
        list = list.stream().filter(each -> StringUtils.isNotEmpty(each.getName()) && !Objects.equals("测试",each.getName())).collect(Collectors.toList());
        int count = 0;
        // 执行数据写入
        List<LinkedHashMap<String, Object>> failList =new ArrayList<>();
        if (list.size() > 0) {
            // 查初始上报临时表中screeningId不为空的list
            List<CerSysteminitImportInfo> infos=cerSysteminitImportInfoService.getAllInitImports();
            // 成功的数据（过滤 errorFlag == 1成功），批量新增
            List<SysteminitImportInfo> successList=new ArrayList<>();
            list.forEach(item->{
                item.setErrorFlag(2);
                item.setErrorMsg("初始上报和初始正式库没有该人员信息，需要先上报，才能进行随访或治疗操作");
                infos.forEach(each->{
                    if (Objects.equals(item.getScreeningId(),each.getScreeningId())) {
                        item.setErrorMsg("治疗正式库中，已存在该人员的治疗数据");
                        String initId = each.getId();
                        // 查治疗正式库中是否存在
                        if (getOfficalCountByInitId(initId) == 0){
                            SysteminitImportInfo systeminitImportInfo =new SysteminitImportInfo();
                            BeanUtils.copyProperties(item,systeminitImportInfo);
                            systeminitImportInfo.setErrorFlag(1);
                            systeminitImportInfo.setInitId(initId);
                            successList.add(systeminitImportInfo);
                        }
                    }
                });
            });
            // 失败列表
            list.stream().filter(each -> each.getErrorFlag()== 2 ).forEach(item ->{
                failList.add(cerSysteminitImportInfoService.getLinkedMapByList(item, item.getErrorMsg() ));
            });
            // 成功数据
            if (!CollectionUtils.isEmpty(successList)) {
                List<String> updateIds=new ArrayList<>();
                List<String> initIds = successList.stream().map(SysteminitImportInfo::getInitId).collect(Collectors.toList());
                List<CerTreatmentInfo> tempList=cerTreatmentInfoService.getTreatmentByInitId(initIds);
                successList.forEach(item->{
                    tempList.forEach(each->{
                        if (Objects.equals(each.getSysteminitId(),item.getInitId())) {
                            // 治疗列表存在，但是治疗正式库不存在：【临时状态：3；其他情况是1】
                            item.setErrorFlag(3);
                            item.setCerTreatmentInfo(each);
                        }
                    });
                });
                List<CerTreatmentInfo> treatmentInfoSuccessList=new ArrayList<>();
                List<CerTreatmentOfficalInfo> treatmentOfficalSuccessList=new ArrayList<>();
                for (SysteminitImportInfo info : successList) {
                    // 查治疗列表是否存在，① 不存在，补充治疗列表数据和治疗正式库相应数据 ②存在，增加治疗正式库数据
                    String initId = info.getInitId();
                    String treatmentId = UuidUtil.get32UUID();
                    if (info.getErrorFlag() == 1) {
                        // 说明：治疗列表不存在，且治疗正式库不存在
                        // 治疗信息只获取id 、initId、sgblCode、bmblCode、wblCode、sezcCode、njjc【求的，根据是否有内镜号判断】、dye、isHj、blzdStaff
                        CerTreatmentInfo cerTreatmentInfo = new CerTreatmentInfo();
                        cerTreatmentInfo.setId(treatmentId);
                        cerTreatmentInfo.setSysteminitId(initId);
                        // 病例代碼
                        cerTreatmentInfo.setSgblCode(info.getSgblCode());
                        cerTreatmentInfo.setBmblCode(info.getBmblCode());
                        cerTreatmentInfo.setWblCode(info.getWblCode());
                        cerTreatmentInfo.setSezcCode(info.getSezcCode());
                        // 内镜检查（是1、否2）
                        cerTreatmentInfo.setNjjc(StringUtils.isNotEmpty(info.getNjNum())?"1":"2");
                        // 染色类别
                        cerTreatmentInfo.setDye(cerTreatmentInfoService.setDyeCode(info.getDye()));
                        // 是否活检
                        cerTreatmentInfo.setIsHj(cerTreatmentInfoService.setIsHj(info.getIsHj()));
                        // 病理诊断医师
                        cerTreatmentInfo.setBlzdStaff(info.getBlzdStaff());
                        cerTreatmentInfo.setIsPublish(1);
                        cerTreatmentInfo.setIsHaveError(1);
                        cerTreatmentInfo.setCountrySource("1");
                        cerTreatmentInfo.setErrorMessage(cerTreatmentInfoService.addValidation().toString());
                        treatmentInfoSuccessList.add(cerTreatmentInfo);
                        CerTreatmentOfficalInfo cerTreatmentOfficalInfo=new CerTreatmentOfficalInfo();
                        BeanUtils.copyProperties(cerTreatmentInfo,cerTreatmentOfficalInfo);
                        cerTreatmentOfficalInfo.setId(UuidUtil.get32UUID());
                        cerTreatmentOfficalInfo.setCountrySource("1");
                        treatmentOfficalSuccessList.add(cerTreatmentOfficalInfo);
                    }else {
                        // 说明：治疗列表存在，但是治疗正式库不存在
                        CerTreatmentInfo cerTreatmentInfo = info.getCerTreatmentInfo();
                        updateIds.add(cerTreatmentInfo.getId());
                        CerTreatmentOfficalInfo cerTreatmentOfficalInfo=new CerTreatmentOfficalInfo();
                        BeanUtils.copyProperties(cerTreatmentInfo,cerTreatmentOfficalInfo);
                        cerTreatmentOfficalInfo.setId(UuidUtil.get32UUID());
                        cerTreatmentOfficalInfo.setCountrySource("1");
                        treatmentOfficalSuccessList.add(cerTreatmentOfficalInfo);
                    }
                }
                if (!CollectionUtils.isEmpty(treatmentInfoSuccessList)) {
                    cerTreatmentInfoService.addBatchCerTreatmentInfo(treatmentInfoSuccessList);
                }
                if (!CollectionUtils.isEmpty(treatmentOfficalSuccessList)) {
                    count += cerTreatmentOfficalInfoMapper.addBatchTreatmentOfficalInfo(treatmentOfficalSuccessList);
                }
                if (!CollectionUtils.isEmpty(updateIds)) {
                    // 最后，把治疗列表逻辑删除
                    cerTreatmentInfoService.setIsPublishByInfoIds(updateIds);
                }

            }
        }
        // 组装表头
        List<String> headList = Arrays.asList(
                "省份",
                "城市",
                "区县",
                "乡镇",
                "村",
                "机构名称",
                "调查对象ID号",
                "姓名",
                "性别",
//                "筛查类型",
                "生日",
                "民族",
                "身份证号",
                "地址",
                "联系电话",
                "筛查类型",
                "随访次数",
                "内镜号",
                "是否无痛",
                "染色类别",
                "是否活检",
                "内镜诊疗日期",
                "Hp",
                "Hp检测方法",
                "图片数量",
                "内镜诊断",
                "内镜诊断医师",
                "内镜审核医师",
                "病理号",
                "病理报告日期",
                "食管病理诊断代码",
                "贲门病理诊断代码",
                "胃病理诊断代码",
                "十二指肠病理诊断代码",
                "病理诊断医师",
                "病理审核医师",
                "病理诊断",
                "导入错误原因");
        try {
            // 导出
            if (!CollectionUtils.isEmpty(failList)) {
//                String s = ExcelUtils.downloadExcel(headList, failList, "导入失败数据导出", response, cerPersonFileInDisk);
                File downloadExcelFile = ExcelUtils.downloadExcelFile(headList, failList, "导入失败数据导出", response, cerPersonFileInDisk);
                String upload = aliyunOssService.upload(downloadExcelFile);
                HashMap<String,Object> res =new HashMap<>();
                res.put("errorFile", upload);
                String msg ="导入失败"+failList.size()+"条";
                if (count>0) {
                    msg += "，导入成功"+count+"条数据";
                }
                return JsonObj.success(res,msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonObj.error("错误数据导出失败");
        }
        return JsonObj.success("导入成功"+count+"条数据");
    }

    private int getOfficalCountByInitId(String initId) {
        return cerTreatmentOfficalInfoMapper.getOfficalCountByInitId(initId);
    }
}
